// 消息转发的模块
#pragma once
#include <iostream>
#include <string>
#include <list>
#include <memory>
#include <sys/types.h>
#include <sys/socket.h>
#include <unordered_map>
#include "InetAddr.hpp"

class UserInerface
{
public:
    virtual ~UserInerface()=default; //=0是纯虚函数子类必须重写，如果不重写子类也是抽象类无法实例化
    virtual void SenTo(int sockfd, const std::string &message) = 0;
    virtual bool operator==(const InetAddr &u) = 0;
};

class User : public UserInerface
{
public:
    User(const InetAddr &id)
        : _id(id)
    {
    }
    void SenTo(int sockfd, const std::string &message) override // 显示说明符声明一个虚函数重写的同名函数
    {
        std::cout << "send message to" << _id.Addr() << "info: " << message << std::endl;
        int n = ::sendto(sockfd, message.c_str(), message.size(), 0, _id.NetAddr(), _id.NetAddrLen());
        (void)n; // 要做判断的，这里偷懒了。
    }
    bool operator==(const InetAddr &u) override
    {
        return _id == u;
    }
    ~User() {}

private:
    InetAddr _id;
};

// 对用户消息进行路由
// UserManager里把所有的用户管理起来！
// 这种设计模式是观察者模式，所有的用户是观察者，一但有任务发生了发给我
// observer
class UserManager
{
public:
    UserManager()
    {
    }
    void AddUser(InetAddr &id)
    {
        // 方法1：利用hash去找是否已经存在O(1)
        //  auto it = _check.find(std::make_shared<User>(id));
        //  if (it == _check.end())
        //  {
        //      _online_user.push_back(std::make_shared<User>(id));
        //      _check.emplace(std::make_shared<User>(id),true);
        //  }
        // 方法2：重载operator==，for循环去判断是否存在O(n)
        for (auto &e : _online_user)
        {
            if (*e == id)
            {
                std::cout << id.Addr() << "用户已经存在" << std::endl;
                return;
            }
        }
        std::cout << "新增该用户：" << id.Addr() << std::endl;

        _online_user.push_back(std::make_shared<User>(id)); // 多态，我定义是基类初始化时子类
        // 方法3：定义一个GetIP()通过返回值去判断。
    }
    void DelUser(const InetAddr &id)
    {
    }
    void Router(int sockfd, const std::string &message)
    {
        for (auto &user : _online_user)
        {
            user->SenTo(sockfd, message);
        }
    }
    ~UserManager()
    {
    }

private:
    std::list<std::shared_ptr<UserInerface>> _online_user;
    // 方法1：//std::unordered_map<std::shared_ptr<UserInerface>, bool> _check;
};